/**
 * call(context,args) context为null或者undefined时候this默认为window,如果是基本类型数据，则会将变成包装对象，如1变成Number{1}
 * call第二个参数接收多个单个参数,不是数组
 *
 * 思路:a.call(b) ，我们目的就是为了实现a调用时候this变成b,可以利用this隐性绑定规则，如对象 obj.fn ，那么fn方法中的this就是obj
 * 注意：需要判断null/undefined  ->window
 *      基本数据类型 -》包装后的
 *      object      -> object
 *
 *
 * Object(arg) 基本数据类型返回包装后的，对象返回源对象，null/undefined返回空对象
 *
 * @param {*} context 要改变this指向的数据,在调用 func 时要使用的 this 值。如果函数不在严格模式下，null 和 undefined 将被替换为全局对象，并且原始值将被转换为对象。
 * @param  {...any} args 其他参数
 */
Function.prototype.myCall = function (context, ...args) {
  // 检验
  if (typeof this !== "function") throw new Error("myCall must be called by a function");

  // 判断context类型
  context = context != null && context != undefined ? Object(context) : window;

  // 唯一的属性名，不和原型链冲突
  const _pro = Symbol("p");
  // 绑定this
  context[_pro] = this;
  // 执行
  let result = context[_pro](...args);
  // 删除我们加的属性
  delete context[_pro];

  return result;
};

// eg:
function fn(...arg) {
  fn1.myCall(1, arg);
}

function fn1(arg, arg1) {
  console.log("arg2", arg, arg1);
  console.log(this);
}

fn(1, 2, 3);
